# ocr_ngrok_service.py (已更新)

import os
import time
from flask import Flask, request, jsonify, render_template_string
from paddleocr import PaddleOCR
from werkzeug.utils import secure_filename
from flask_cors import CORS
from pyngrok import ngrok
from threading import Thread

# ----------------- 配置 -----------------
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg'}
UPLOAD_FOLDER = 'uploads' 
PORT = 5000 
INI_FILE = 'server_address.ini' # 新增：配置文件名

# 请替换为您自己的 ngrok 授权码！
NGROK_AUTH_TOKEN = "2xvl1u6E1u8CSPHttvE5rrhNLC3_7WppSEwxW7qtYvnHVfarp" 

app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
CORS(app)
ocr = None

# ----------------- 辅助函数 -----------------

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

def write_server_address(url):
    """写入公网地址到INI文件"""
    try:
        with open(INI_FILE, 'w') as f:
            f.write(f"server_address={url}\n")
        print(f"🎉 成功将公网地址写入 {INI_FILE}")
    except Exception as e:
        print(f"❌ 写入 {INI_FILE} 失败: {e}")

# ----------------- 路由定义 -----------------

@app.route('/')
def index():
    """提供一个简单的 HTML 页面访问提示。"""
    return render_template_string('''
        <h1>PaddleOCR Flask 服务已启动 (返回文本模式)</h1>
        <p>服务运行在 **http://127.0.0.1:5000/**</p>
        <p>请访问 **<script>document.write(window.location.protocol + "//" + window.location.host)</script>/upload_image** 接口上传图片进行识别。</p>
        <p>如果服务通过 ngrok 访问，请使用 ngrok 提供的公网 URL。</p>
    ''')

@app.route('/upload_image', methods=['POST'])
def upload_image():
    """处理图片上传和文字识别的 API 接口。"""
    global ocr

    if ocr is None:
         return jsonify({
            'code': 503,
            'message': 'PaddleOCR 尚未初始化完毕，请稍后再试。'
        }), 503
    
    # ... (文件检查逻辑不变) ...
    if 'file' not in request.files or request.files['file'].filename == '' or not allowed_file(request.files['file'].filename):
        return jsonify({'code': 400, 'message': '文件类型不被允许或未包含文件'}), 400

    file = request.files['file']
    filename = secure_filename(file.filename)
    temp_path = os.path.join(app.config['UPLOAD_FOLDER'], f'temp_ocr_{time.time()}_{filename}')
    
    try:
        os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
        file.save(temp_path)

        print(f"[INFO] 文件已接收: {filename}。开始OCR识别...")

        # 调用 OCR 引擎 (已修正为 .predict())
        start_time = time.time()
        result = ocr.predict(temp_path) 
        end_time = time.time()
        
        recognized_text = ""
        # 3.3. 解析识别结果 (注意：PaddleOCR的返回格式依赖版本，这里保留原有的逻辑但注释了不兼容的部分)
        if result and result[0]:
            # 采用更通用的列表解析方式获取所有识别文本
            texts = [line[1][0] for line in result[0]]
            recognized_text = "\n".join(texts)
            
            # 您原代码中的这行：recognized_text = result[0]['rec_texts'][0] 
            # 经查可能与新的PaddleOCR版本返回格式不兼容，故注释或替换。
            # 如果您的版本确实返回了字典，请取消以下注释：
            recognized_text = result[0]['rec_texts'][0] 
        
        print(f"[SUCCESS] OCR识别完成！耗时: {end_time - start_time:.2f} 秒。")
        os.remove(temp_path)

        return jsonify({
            'code': 200,
            'message': '图片识别处理成功',
            'recognized_text': recognized_text
        })

    except Exception as e:
        print(f"[ERROR] 识别过程中发生错误: {e}")
        if os.path.exists(temp_path): os.remove(temp_path)
        return jsonify({'code': 500, 'message': f'服务端识别错误: {str(e)}'}), 500


# ----------------- 启动主程序 -----------------

def start_flask():
    """在后台线程中启动 Flask 服务"""
    app.run(port=PORT, host='127.0.0.1', debug=False, use_reloader=False)

def init_ocr():
    """初始化 PaddleOCR 实例"""
    global ocr
    print("正在初始化 PaddleOCR，这可能需要一些时间...")
    ocr = PaddleOCR(use_doc_orientation_classify=False, use_doc_unwarping=False, use_textline_orientation=False) 
    print("✅ PaddleOCR 初始化完成。")

def main():
    
    init_ocr()
    print(f"\n--- 1. 启动 Flask 服务于 http://127.0.0.1:{PORT} ---")
    flask_thread = Thread(target=start_flask)
    flask_thread.start()
    time.sleep(3) 

    if NGROK_AUTH_TOKEN:
        print(f"\n--- 2. 配置 ngrok 授权码... ---")
        try:
            ngrok.set_auth_token(NGROK_AUTH_TOKEN)
        except Exception as e:
            print(f"❌ ngrok 授权码配置失败，请检查授权码是否正确: {e}")
            return
    
    print("\n--- 3. 创建 ngrok 隧道 ---")
    try:
        tunnel = ngrok.connect(PORT, proto="http")
        public_url = tunnel.public_url

        # ***** 新增：写入公网地址 *****
        write_server_address(public_url)
        # ******************************

        print(f"\n✅ ngrok 隧道创建成功！")
        print(f"公网访问地址 (Public URL): {public_url}")
        print("---------------------------------------")
        print("隧道已启动。请使用 **testsbapp.html** 访问服务。")
        print("按 Ctrl+C 停止服务。")
        print("---------------------------------------")

        while True:
            time.sleep(1)

    except Exception as e:
        print(f"\n❌ ngrok 启动失败：{e}")
        
    finally:
        print("\n--- 4. 清理并关闭 ngrok 隧道 ---")
        ngrok.kill()
        if os.path.exists(INI_FILE):
             os.remove(INI_FILE) # 停止服务时删除 ini 文件
        print("程序已退出。")
        os._exit(0)

if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        print("\n用户中断，正在退出...")
        ngrok.kill()
        if os.path.exists(INI_FILE):
             os.remove(INI_FILE)
        os._exit(0)